using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;


namespace C4F.DevKit.RSS.ScreenSaverWPF
{
    // The main screensaver window.
    public partial class MainWindow : System.Windows.Window
    {
        // Mouse position is tracked to determine when the screensaver should close.
        Point _lastKnownMousePos;
        // Timer used determine when to display the next picutre.
        DispatcherTimer _refreshTimer;
        // The RSS feed list to use.
        FeedList _feedList = null;
        

        public MainWindow()
        {
            InitializeComponent();

            this._lastKnownMousePos.X = -1;
            this._lastKnownMousePos.Y = -1;

            this.MouseMove += new MouseEventHandler(MainWindow_MouseMove);
            this.MouseDown += new MouseButtonEventHandler(MainWindow_MouseDown);
            this.KeyDown += new KeyEventHandler(MainWindow_KeyDown);
        }
        
        // Setup the screensaver after this window is loaded.
        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            // Using the IsVisibleChanged event as a trigger to determine when to
            // start the storyboard animation for the text area of the screensaver.
            this.textArea.IsVisibleChanged += new DependencyPropertyChangedEventHandler(textArea_IsVisibleChanged);

            // Initialize and load the feed list.
            try
            {
                this._feedList = new FeedList();
                this._feedList.Load();
            }
            catch (FileNotFoundException)
            {
                string msg = ResourcesWrapper.FeedsInteropErrorText;

                MessageBox.Show(
                    msg, 
                    ResourcesWrapper.FeedsLoadErrorText, 
                    MessageBoxButton.OK, MessageBoxImage.Error);

                Close();
                return;
            }

            DisplayCurrentImage();

            // Start the timer using the value provided by the settings.
            this._refreshTimer = new DispatcherTimer(DispatcherPriority.Normal);
            this._refreshTimer.Interval = new TimeSpan(0, 0, SettingsWrapper.FadePauseInterval);
            this._refreshTimer.Tick += new EventHandler(_refreshTimer_Tick);
            this._refreshTimer.Start();
        }


        void textArea_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            // Determine visibility (true or false).
            string visible = e.NewValue.ToString();

            if (visible == bool.TrueString)
            {
                // Start storyboard when visibility goes from false to true.
                BeginTextAreaStoryboard();
            }
        }

        
        void _refreshTimer_Tick(object sender, EventArgs e)
        {
            // Hide text area before displaying new image.
            textArea.Visibility = Visibility.Hidden;
            this._refreshTimer.IsEnabled = false;

            // Show next image.
            this._feedList.MoveNext();
            DisplayCurrentImage();

            this._refreshTimer.IsEnabled = true;
        }

        // Displays the current image (and text description).
        private void DisplayCurrentImage()
        {
            Uri imageLoc = new Uri(this._feedList.CurrentItem.Enclosure.FullName);
            string textDesc = this._feedList.CurrentItem.Title;

            DisplayImage(imageLoc);
            DisplayText(textDesc);

            textArea.Visibility = Visibility.Visible;
        }

        void DisplayImage(Uri imgUri)
        {
            if (imgUri == null)
            { throw new ArgumentNullException("uri"); }

            // Use the actual width of this window minus a small
            // amount of buffer area around the image when displaying.
            double w = this.ActualWidth - 25;
            double h = this.ActualHeight - 25;

            drawCanvas.Width = w;
            drawCanvas.Height = h;
            picContainer.Width = w;
            picContainer.Height = h;

            // The default RSS text (see Resources) contains two default image references,
            // arbitrarily called @SSaverBackground1 and @SSaverBackground2.
            if (imgUri.AbsolutePath.Contains("@SSaverBackground1"))
            {
                // WPF applications use the Pack URI Scheme to identify data resources.
                imgUri = new Uri("pack://application:,,/Resources/SSaverBackground1.jpg");
            }
            else if (imgUri.AbsolutePath.Contains("@SSaverBackground2"))
            {
                imgUri = new Uri("pack://application:,,/Resources/SSaverBackground2.jpg");
            }

            // Create a BitmapImage instance.
            BitmapImage bitmap = null;
            try
            {
                bitmap = new BitmapImage(imgUri);
            }
            catch (Exception)
            {
                bitmap = new BitmapImage();
            }

            // Assign the new BitmapImage instance to the 'pic' element.
            pic.Source = bitmap;
        }

        private void DisplayText(string textDesc)
        {
            if (textDesc == null)
            { throw new ArgumentNullException("textDesc"); }

            textAreaText.Text = textDesc;
        }

        private void BeginTextAreaStoryboard()
        {
            // Create animation to go from value 0.0 to 1.0 over the configured interval.
            DoubleAnimation anim = new DoubleAnimation(0, 1, 
                new Duration(new TimeSpan(0, 0, SettingsWrapper.FadePauseInterval)), FillBehavior.HoldEnd);
            
            // Animate the text area of the screensaver and affect its opacity.
            Storyboard.SetTargetName(anim, "textArea");
            Storyboard.SetTargetProperty(anim, new PropertyPath(Canvas.OpacityProperty));

            // Create and start the storyboard containing the animation.
            Storyboard fadeIn = new Storyboard();
            fadeIn.Children.Add(anim);

            textArea.BeginStoryboard(fadeIn);
        }

        void MainWindow_MouseMove(object sender, MouseEventArgs e)
        {
            // Acquire current position.
            Point currPos = e.GetPosition(this);

            // Determine if mouse movement warrants closing the screensaver.
            if (this._lastKnownMousePos.X == -1 && this._lastKnownMousePos.Y == -1)
            {
                // Ignore the case when this event handler is first fired.
                this._lastKnownMousePos = currPos;
            }
            else
            {
                // If the mouse has moved significantly since first call, close the app.
                if ((Math.Abs(currPos.X - this._lastKnownMousePos.X) > 50) ||
                    (Math.Abs(currPos.Y - this._lastKnownMousePos.Y) > 50))
                {
                    this.Close();
                }
            }
        }

        void MainWindow_MouseDown(object sender, MouseButtonEventArgs e)
        {
            this.Close();
        }

        void MainWindow_KeyDown(object sender, KeyEventArgs e)
        {
            this.Close();
        }
    }
}